package taskmanager

import (
	"context"
	"errors"
	"fmt"
	"sync"
	"time"

	"dev.ixmxm.top/rms/boot"
	"dev.ixmxm.top/rms/codes"
	"dev.ixmxm.top/rms/model"
	"dev.ixmxm.top/rms/utils/function"
	"dev.ixmxm.top/rms/utils/log"
	"dev.ixmxm.top/rms/utils/page"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

func NewTaskManager(db *boot.MongoDB) *TaskManager {
	rm := &TaskManager{db: db, taskStatusUpdateChan: make(chan model.Task, 2000), taskStatusEnum: make(map[int]string)}
	var vector = []string{"未定义", "已登记", "已分配", "执行中", "已完成", "暂停中", "已暂停", "继续中", "取消中", "已取消", "中转中", "完成中", "充电中", "已解析", "避让中", "未定义", "错误"}
	for idx, str := range vector {
		rm.taskStatusEnum[idx] = str
	}
	return rm
}

type TaskManager struct {
	db                   *boot.MongoDB
	bindMainTaskLocker   sync.Mutex
	taskStatusEnum       map[int]string
	taskStatusUpdateChan chan model.Task
	SystemConfig         *model.SystemConfig //系统配置(缓存),不可直接赋值保存，调用SaveSystemConfigToCache保存
	UpdateLock           sync.Mutex
}

//IsBusy 有任务正在运行
func (m *TaskManager) IsBusy(ctx context.Context) (bool, codes.Code) {
	count, err := m.db.Collection(ctx, model.Task{}.TableName()).CountDocuments(ctx, bson.M{"status": bson.M{"$in": model.TaskRunningStatus()}})
	if err != nil {
		log.ErrorfWithContext(ctx, "count running tasks from db error:%s", err.Error())
		return false, codes.ErrDatabase.Wrap(err)
	}
	return count > 0, nil
}

//初始化任务ID索引
func (m *TaskManager) TaskIdInit(ctx context.Context) codes.Code {
	dbRes := m.db.Collection(ctx, fmt.Sprintf("%s_index", model.Task{}.TableName())).FindOne(ctx, bson.M{})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get taskId from db error:%s", dbRes.Err().Error())
		return codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		_, err := m.db.Collection(ctx, fmt.Sprintf("%s_index", model.Task{}.TableName())).InsertOne(ctx, bson.M{"id": 1})
		if err != nil {
			return codes.ErrDatabase.Wrap(err)
		}
	}
	return nil
}

//AddToDB 添加任务到数据库
func (m *TaskManager) AddToDB(ctx context.Context, task *model.Task) (*model.Task, codes.Code) {
	// task.Status = model.TaskStatusRegister
	task.CreatedTime = time.Now()
	if task.Type == model.TaskTypeCharge {
		task.Grade = 99
	} else if task.Type == model.TaskTypeStandBy {
		task.Grade = 1
	}
	if err := m.db.Collection(ctx, fmt.Sprintf("%s_index", task.TableName())).FindOneAndUpdate(ctx, bson.M{}, bson.M{"$inc": bson.M{"id": 1}}, &options.FindOneAndUpdateOptions{Projection: bson.M{"_id": 0}, Upsert: function.BoolPtr(true)}).Decode(&task); err != nil && !errors.Is(err, mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "insert task to db error,can not get index:%s", err.Error())
		return nil, codes.ErrDatabase.Wrap(err)
	}
	_, errInsert := m.db.Collection(ctx, task.TableName()).InsertOne(ctx, task)
	log.Warnf("API添加新任务：%+v", task)
	if errInsert != nil {
		log.ErrorfWithContext(ctx, "insert task to db error:%s", errInsert.Error())
		return nil, codes.ErrDatabase.Wrap(errInsert)
	}
	m.sendTaskUpdate(task)
	return task, nil
}

//根据外部任务编号检测任务是否存在
func (m *TaskManager) TaskExistsFromDBByExternalTaskCode(ctx context.Context, externalTaskCode string) (bool, codes.Code) {
	dbRes := m.db.Collection(ctx, model.Task{}.TableName()).FindOne(ctx, bson.M{"external_task_code": externalTaskCode})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get externalTaskCode:%d from db error:%s", externalTaskCode, dbRes.Err().Error())
		return true, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find task:%d",id)
		return false, nil
	}
	return true, nil
}

//根据任务id获取任务
func (m *TaskManager) GetTaskFromDB(ctx context.Context, id uint64) (*model.Task, codes.Code) {
	dbRes := m.db.Collection(ctx, model.Task{}.TableName()).FindOne(ctx, bson.M{"id": id})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get task:%d from db error:%s", id, dbRes.Err().Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find task:%d",id)
		return nil, codes.ErrTaskNotExists
	}
	task := new(model.Task)
	if errBind := dbRes.Decode(task); errBind != nil {
		log.ErrorfWithContext(ctx, "bind task:%d from db error:%s", id, errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return task, nil
}

//从数据库获得目标点相同的放货任务
func (m *TaskManager) GetAllSameGroundLocationTaskFromDB(ctx context.Context, mapName string, taskId uint64, targetList []string) ([]*model.Task, codes.Code) {
	dbRes, err := m.db.Collection(ctx, model.Task{}.TableName()).Find(ctx, bson.M{"target_site_id": bson.M{"$in": targetList}, "map_name": mapName, "type": model.TaskTypePut, "status": bson.M{"$in": model.TaskAssignStatus()}, "id": bson.M{"$ne": taskId}})
	if err != nil {
		log.ErrorfWithContext(ctx, "get all SameGroundLocationTask from db error:%s", err.Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find robot running:%s task",agvID)
		return nil, nil
	}
	tasks := make([]*model.Task, 0)
	if errBind := dbRes.All(ctx, &tasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind all SameGroundLocationTask from db error:%s", errBind.Error())
		return nil, codes.ErrTaskNotExists
	}
	return tasks, nil
}

//从数据库获得目标点相同的放货任务
func (m *TaskManager) GetAllSameGroundLocationPickTaskFromDB(ctx context.Context, mapName string, taskId uint64, targetList []string) ([]*model.Task, codes.Code) {
	dbRes, err := m.db.Collection(ctx, model.Task{}.TableName()).Find(ctx, bson.M{"target_site_id": bson.M{"$in": targetList}, "map_name": mapName, "type": model.TaskTypePick, "status": model.TaskStatusRegister, "id": bson.M{"$ne": taskId}})
	if err != nil {
		log.ErrorfWithContext(ctx, "get all SameGroundLocationTask from db error:%s", err.Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find robot running:%s task",agvID)
		return nil, nil
	}
	tasks := make([]*model.Task, 0)
	if errBind := dbRes.All(ctx, &tasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind all SameGroundLocationTask from db error:%s", errBind.Error())
		return nil, codes.ErrTaskNotExists
	}
	return tasks, nil
}

// 向数据库删除一条任务、任务绑定以及对应子任务
func (m *TaskManager) DeleteTaskToDB(ctx context.Context, taskid uint64) codes.Code {
	log.Infof("开始删除任务(%d)下的所有任务、任务绑定和子任务", taskid)
	ctxTx := boot.Begin(ctx)
	_, err := m.db.Collection(ctxTx, model.Task{}.TableName()).DeleteOne(ctxTx, bson.M{"id": taskid})
	if err != nil {
		ctxTx.Rollback()
		log.ErrorfWithContext(ctx, "Delete one task from db. taskId:%d error:%s", taskid, err.Error())
		return codes.ErrDatabase.Wrap(err)
	}
	_, err = m.db.Collection(ctxTx, model.MainTask{}.TableName()).DeleteOne(ctxTx, bson.M{"task_id": taskid})
	if err != nil {
		ctxTx.Rollback()
		log.ErrorfWithContext(ctx, "Delete one maintask from db. taskId:%d error:%s", taskid, err.Error())
		return codes.ErrDatabase.Wrap(err)
	}
	_, err = m.db.Collection(ctxTx, model.Subtask{}.TableName()).DeleteMany(ctxTx, bson.M{"task_id": taskid})
	if err != nil {
		ctxTx.Rollback()
		log.ErrorfWithContext(ctx, "Delete Many subtasks from db. taskId:%d error:%s", taskid, err.Error())
		return codes.ErrDatabase.Wrap(err)
	}
	ctxTx.Commit()
	return nil
}

// 向数据库清空任务(所有任务、任务ID索引、任务绑定和子任务、子任务ID索引)
func (m *TaskManager) ClearTaskToDB(ctx context.Context) codes.Code {
	log.Infof("开始清空任务(所有任务、任务ID索引、任务绑定和子任务、子任务ID索引)")
	ctxTx := boot.Begin(ctx)
	_, err := m.db.Collection(ctxTx, fmt.Sprintf("%s_index", model.Task{}.TableName())).UpdateOne(ctxTx, bson.M{}, bson.M{"$set": bson.M{"id": 1}})
	if err != nil {
		return codes.ErrDatabase.Wrap(err)
	}
	_, err = m.db.Collection(ctxTx, fmt.Sprintf("%s_index", model.Subtask{}.TableName())).UpdateOne(ctxTx, bson.M{}, bson.M{"$set": bson.M{"id": 1}})
	if err != nil {
		return codes.ErrDatabase.Wrap(err)
	}
	err = m.db.Collection(ctx, model.FailedPathPlan{}.TableName()).Drop(ctx)
	if err != nil {
		ctxTx.Rollback()
		log.ErrorfWithContext(ctx, "clear failedplan from db. error:%s", err.Error())
		return codes.ErrDatabase.Wrap(err)
	}
	err = m.db.Collection(ctx, model.Task{}.TableName()).Drop(ctx)
	if err != nil {
		ctxTx.Rollback()
		log.ErrorfWithContext(ctx, "clear task from db. error:%s", err.Error())
		return codes.ErrDatabase.Wrap(err)
	}
	err = m.db.Collection(ctx, model.MainTask{}.TableName()).Drop(ctx)
	if err != nil {
		ctxTx.Rollback()
		log.ErrorfWithContext(ctx, "clear maintask from db. error:%s", err.Error())
		return codes.ErrDatabase.Wrap(err)
	}
	err = m.db.Collection(ctx, model.Subtask{}.TableName()).Drop(ctx)
	if err != nil {
		ctxTx.Rollback()
		log.ErrorfWithContext(ctx, "Delete Many subtasks from db. error:%s", err.Error())
		return codes.ErrDatabase.Wrap(err)
	}
	ctxTx.Commit()
	return nil
}

//GetAllWaitingTasksFromDB 从数据库获得所有等待中的任务
func (m *TaskManager) GetAllWaitingTasksFromDB(ctx context.Context) ([]*model.Task, codes.Code) {
	dbRes, err := m.db.Collection(ctx, model.Task{}.TableName()).Find(ctx, bson.M{"status": bson.M{"$in": model.TaskWaitingStatus()}}, &options.FindOptions{Sort: bson.M{"created_time": 1}})
	if err != nil {
		log.ErrorfWithContext(ctx, "get all waiting tasks from db error:%s", err.Error())
		return nil, codes.ErrDatabase.Wrap(err)
	}
	tasks := make([]*model.Task, 0)
	if errBind := dbRes.All(ctx, &tasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind all waiting tasks from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return tasks, nil
}

// 从数据库获得所有已完成未上报的任务
func (m *TaskManager) GetAllFinishReportTasksFromDB() ([]*model.Task, codes.Code) {
	ctx := context.Background()
	dbRes, err := m.db.Collection(ctx, model.Task{}.TableName()).Find(ctx, bson.M{"status": model.TaskStatusFinish, "report": 0})
	if err != nil {
		log.ErrorfWithContext(ctx, "从数据库获得所有已完成未上报的任务 error:%s", err.Error())
		return nil, codes.ErrDatabase.Wrap(err)
	}
	tasks := make([]*model.Task, 0)
	if errBind := dbRes.All(ctx, &tasks); errBind != nil {
		log.ErrorfWithContext(ctx, "从数据库获得所有已完成未上报的任务 error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return tasks, nil
}

//数据库更改任务上报完成
func (m *TaskManager) SetTaskReportToDB(taskId uint64) codes.Code {
	ctx := context.Background()
	data := bson.M{"report": 1}
	dbRes := m.db.Collection(ctx, model.Task{}.TableName()).FindOneAndUpdate(ctx, bson.M{"id": taskId}, bson.M{"$set": data})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "update report task:%d to db error:%s", taskId, dbRes.Err().Error())
		return codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find task:%d",id)
		return codes.ErrTaskNotExists
	}
	return nil
}

//从数据库获得所有状态的任务(按照优先级和创建时间排序)
func (m *TaskManager) GetAllStatusTasksFromDB(ctx context.Context, status []model.TaskStatus) ([]*model.Task, codes.Code) {
	sort := bson.D{
		bson.E{"grade", -1},
		bson.E{"created_time", 1},
	}
	//dbRes, err := m.db.Collection(ctx, model.Task{}.TableName()).Find(ctx, bson.M{"status": bson.M{"$in": status}}, &options.FindOptions{Sort: bson.M{"created_time": 1}})
	dbRes, err := m.db.Collection(ctx, model.Task{}.TableName()).Find(ctx, bson.M{"status": bson.M{"$in": status}}, &options.FindOptions{Sort: sort})
	if err != nil {
		log.ErrorfWithContext(ctx, "get all running tasks from db error:%s", err.Error())
		return nil, codes.ErrDatabase.Wrap(err)
	}
	tasks := make([]*model.Task, 0)
	if errBind := dbRes.All(ctx, &tasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind all running tasks from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return tasks, nil
}

//从数据库获得所有状态的任务(按照优先级和创建时间排序)
func (m *TaskManager) GetAllStatusOrCurrentTaskFromDB(ctx context.Context, status []model.TaskStatus, subTask *model.Subtask) ([]*model.Task, codes.Code) {
	sort := bson.D{
		bson.E{"grade", -1},
		bson.E{"created_time", 1},
	}
	var filter interface{}
	if subTask != nil {
		filter = bson.M{"$or": bson.A{
			bson.M{"status": bson.M{"$in": status}},
			bson.M{"id": subTask.TaskId},
		},
		}
	} else {
		filter = bson.M{"status": bson.M{"$in": status}}
	}

	//dbRes, err := m.db.Collection(ctx, model.Task{}.TableName()).Find(ctx, bson.M{"status": bson.M{"$in": status}}, &options.FindOptions{Sort: bson.M{"created_time": 1}})
	dbRes, err := m.db.Collection(ctx, model.Task{}.TableName()).Find(ctx, filter, &options.FindOptions{Sort: sort})
	if err != nil {
		log.ErrorfWithContext(ctx, "get all running tasks from db error:%s", err.Error())
		return nil, codes.ErrDatabase.Wrap(err)
	}
	tasks := make([]*model.Task, 0)
	if errBind := dbRes.All(ctx, &tasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind all running tasks from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return tasks, nil
}
func (m *TaskManager) GetAllStatusTasksByMapNameFromDB(ctx context.Context, status []model.TaskStatus, mapName string) ([]*model.Task, codes.Code) {
	sort := bson.D{
		bson.E{"grade", -1},
		bson.E{"created_time", 1},
	}
	//dbRes, err := m.db.Collection(ctx, model.Task{}.TableName()).Find(ctx, bson.M{"status": bson.M{"$in": status}}, &options.FindOptions{Sort: bson.M{"created_time": 1}})
	dbRes, err := m.db.Collection(ctx, model.Task{}.TableName()).Find(ctx, bson.M{"status": bson.M{"$in": status}, "map_name": mapName}, &options.FindOptions{Sort: sort})
	if err != nil {
		log.ErrorfWithContext(ctx, "get all running tasks from db error:%s", err.Error())
		return nil, codes.ErrDatabase.Wrap(err)
	}
	tasks := make([]*model.Task, 0)
	if errBind := dbRes.All(ctx, &tasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind all running tasks from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return tasks, nil
}

//GetDependExternalTaskCode获得依赖任务
func (m *TaskManager) GetDependExternalUnfinishTask(ctx context.Context, dependExternalTaskCode string) (*model.Task, codes.Code) {
	filter := bson.M{
		"external_task_code": dependExternalTaskCode,
		"status":             bson.M{"$nin": model.TaskFinishedStatus()},
	}

	dbRes := m.db.Collection(ctx, model.Task{}.TableName()).FindOne(ctx, filter)
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get unfinished task by dependExternalTaskCode from db error:%s", dbRes.Err().Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		return nil, nil
	}
	task := new(model.Task)
	if errBind := dbRes.Decode(task); errBind != nil {
		log.ErrorfWithContext(ctx, "bind robot assign task from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return task, nil
}

//从数据库获得所有状态的任务(按照优先级和创建时间排序)
func (m *TaskManager) GetAllHaveAgvIdButUnFinishTasksFromDB(ctx context.Context, containsSiteIds []string) ([]*model.Task, codes.Code) {
	sort := bson.D{
		bson.E{"grade", -1},
		bson.E{"created_time", 1},
	}

	dbRes, err := m.db.Collection(ctx, model.Task{}.TableName()).Find(ctx, bson.M{"agv_id": bson.M{"$ne": ""}, "status": bson.M{"$in": model.TaskAssignStatus()}, "target_site_id": bson.M{"$in": containsSiteIds}}, &options.FindOptions{Sort: sort})
	if err != nil {
		log.ErrorfWithContext(ctx, "get all running tasks from db error:%s", err.Error())
		return nil, codes.ErrDatabase.Wrap(err)
	}
	tasks := make([]*model.Task, 0)
	if errBind := dbRes.All(ctx, &tasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind all running tasks from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return tasks, nil
}

//从数据库查找未完成的充电任务
func (m *TaskManager) GetUnFinishedRechargerFromDB(ctx context.Context, agvID string) (*model.Task, codes.Code) {
	dbRes := m.db.Collection(ctx, model.Task{}.TableName()).FindOne(ctx, bson.M{"agv_id": agvID, "type": model.TaskTypeCharge, "status": bson.M{"$in": model.TaskAssignStatus()}})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get robot:%s assign task from db error:%s", agvID, dbRes.Err().Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		return nil, nil
	}
	task := new(model.Task)
	if errBind := dbRes.Decode(task); errBind != nil {
		log.ErrorfWithContext(ctx, "bind robot assign task from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return task, nil
}

//从数据库查找所有未完成的充电任务
func (m *TaskManager) GetUnFinishedRechargerTasksFromDB(ctx context.Context, filterAgvID string, mapName string) ([]*model.Task, codes.Code) {
	//过滤条件
	filter := bson.M{
		"agv_id":   bson.M{"$ne": filterAgvID},
		"map_name": mapName,
		"type":     model.TaskTypeCharge,
		"status":   bson.M{"$nin": model.TaskFinishedStatus()},
	}
	dbRes, err := m.db.Collection(ctx, model.Task{}.TableName()).Find(ctx, filter)
	if err != nil {
		if err == mongo.ErrNoDocuments {
			return nil, nil
		}
		log.ErrorfWithContext(ctx, "get all unfinish recharger tasks from db error:%s", err.Error())
		return nil, codes.ErrDatabase.Wrap(err)
	}
	tasks := make([]*model.Task, 0)
	if errBind := dbRes.All(ctx, &tasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind all unfinish recharger tasks from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return tasks, nil
}

//数据库查找未完成
func (m *TaskManager) GetUnFinishedTaskByLocationInfoFromDB(ctx context.Context, task1 model.Task) (*model.Task, codes.Code) {
	filter := bson.M{"target_site_id": task1.TargetSiteID,
		"target_layer":     task1.TargetLayer,
		"target_direction": task1.TargetDirection,
		"map_name":         task1.MapName,
		"created_time":     bson.M{"$lt": task1.CreatedTime},
		"agv_id":           bson.M{"$ne": task1.AgvId},
		"status":           bson.M{"$nin": model.TaskFinishedStatus()},
	}
	dbRes := m.db.Collection(ctx, model.Task{}.TableName()).FindOne(ctx, filter)
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get unfinished task by location from db error:%s", dbRes.Err().Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		return nil, nil
	}
	task := new(model.Task)
	if errBind := dbRes.Decode(task); errBind != nil {
		log.ErrorfWithContext(ctx, "bind robot assign task from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return task, nil
}

//从数据库获取起点在某地图指定状态，没指定机器人的任务(按照优先级和创建时间排序),
func (m *TaskManager) GetTasksByMapAndStatus(ctx context.Context, mapName string, status []model.TaskStatus, limit *int64) ([]*model.Task, codes.Code) {
	filter := bson.M{"status": bson.M{"$in": status},
		"map_name": mapName,
		"$or": []bson.M{
			bson.M{"agv_id": ""},
			bson.M{"agv_id": nil},
			bson.M{"agv_id": bson.M{"$exists": false}},
		},
	}
	sort := bson.D{
		bson.E{"grade", -1},
		bson.E{"created_time", 1},
	}
	dbRes, err := m.db.Collection(ctx, model.Task{}.TableName()).Find(ctx, filter, &options.FindOptions{Sort: sort, Limit: limit})
	if err != nil {
		if err == mongo.ErrNoDocuments {
			return nil, nil
		}
		log.ErrorfWithContext(ctx, "get all running tasks from db error:%s", err.Error())
		return nil, codes.ErrDatabase.Wrap(err)
	}
	tasks := make([]*model.Task, 0)
	if errBind := dbRes.All(ctx, &tasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind all running tasks from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return tasks, nil
}

//从数据库获取起点在某地图指定状态指定机器人的任务(按照优先级和创建时间排序)
func (m *TaskManager) GetTasksByMapAndAgvIDStatus(ctx context.Context, mapName string, status []model.TaskStatus, agvIDs []string, limit *int64) ([]*model.Task, codes.Code) {
	filter := bson.M{"status": bson.M{"$in": status},
		"map_name": mapName,
		"agv_id":   bson.M{"$in": agvIDs},
	}
	sort := bson.D{
		bson.E{"grade", -1},
		bson.E{"created_time", 1},
	}
	dbRes, err := m.db.Collection(ctx, model.Task{}.TableName()).Find(ctx, filter, &options.FindOptions{Sort: sort, Limit: limit})
	if err != nil {
		if err == mongo.ErrNoDocuments {
			return nil, nil
		}
		log.ErrorfWithContext(ctx, "get all running tasks from db error:%s", err.Error())
		return nil, codes.ErrDatabase.Wrap(err)
	}
	tasks := make([]*model.Task, 0)
	if errBind := dbRes.All(ctx, &tasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind all running tasks from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return tasks, nil
}

//GetStatusTaskForPageFromDB 从数据库获得指定状态的任务，并分页
func (m *TaskManager) GetStatusTaskForPageFromDB(ctx context.Context, status []model.TaskStatus, pageParam page.Params) ([]model.Task, page.PageResult, codes.Code) {
	page.SetPageParams(&pageParam.PageSize, &pageParam.PageIndex, 20)
	filter := bson.M{}
	if len(status) > 0 {
		filter = bson.M{"status": bson.M{"$in": status}}
	}
	total, errCount := m.db.Collection(ctx, model.Task{}.TableName()).CountDocuments(ctx, filter)
	if errCount != nil {
		log.ErrorfWithContext(ctx, "count status task error:%s", errCount.Error())
		return nil, page.PageResult{}, codes.ErrDatabase.Wrap(errCount)
	}
	skip := (pageParam.PageIndex - 1) * pageParam.PageSize
	dbRes, err := m.db.Collection(ctx, model.Task{}.TableName()).Find(ctx, filter, &options.FindOptions{Skip: &skip, Limit: &pageParam.PageSize, Sort: bson.M{"created_time": -1}})
	if err != nil {
		log.ErrorfWithContext(ctx, "get all status tasks from db error:%s", err.Error())
		return nil, page.PageResult{}, codes.ErrDatabase.Wrap(err)
	}
	tasks := make([]model.Task, 0)
	if errBind := dbRes.All(ctx, &tasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind all status tasks from db error:%s", errBind.Error())
		return nil, page.PageResult{}, codes.ErrDatabase.Wrap(errBind)
	}
	return tasks, page.NewPageResult(pageParam.PageSize, pageParam.PageIndex, total), nil
}

//GetStatusTaskForPageFromDB 从数据库获得指定状态的任务，并分页
func (m *TaskManager) GetStatusByTimeTaskForPageFromDB(ctx context.Context, startTime, endTime time.Time, status []model.TaskStatus) ([]*model.Task, codes.Code) {
	// page.SetPageParams(&pageParam.PageSize, &pageParam.PageIndex, 20)
	if endTime.IsZero() {
		endTime = time.Now()
	}
	sort := bson.D{
		bson.E{"grade", -1},
		bson.E{"created_time", 1},
	}
	filter := bson.M{"start_time": bson.M{"$gte": startTime, "$lte": endTime}}

	if len(status) > 0 {
		filter["status"] = bson.M{"$in": status}
	}

	//dbRes, err := m.db.Collection(ctx, model.Task{}.TableName()).Find(ctx, bson.M{"status": bson.M{"$in": status}}, &options.FindOptions{Sort: bson.M{"created_time": 1}})
	dbRes, err := m.db.Collection(ctx, model.Task{}.TableName()).Find(ctx, filter, &options.FindOptions{Sort: sort})
	if err != nil {
		log.ErrorfWithContext(ctx, "get all running tasks from db error:%s", err.Error())
		return nil, codes.ErrDatabase.Wrap(err)
	}
	tasks := make([]*model.Task, 0)
	if errBind := dbRes.All(ctx, &tasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind all running tasks from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return tasks, nil
}

//GetStatusTaskForPagebyTaskIdFromDB 从数据库获得指定状态的任务，并分页
func (m *TaskManager) GetStatusTaskForPagebyTaskIdFromDB(ctx context.Context, status []model.TaskStatus, pageParam page.Params, taskId uint64) ([]model.Task, page.PageResult, codes.Code) {
	page.SetPageParams(&pageParam.PageSize, &pageParam.PageIndex, 20)
	filter := bson.M{
		"id": taskId,
	}
	if len(status) > 0 {
		filter = bson.M{
			"status": bson.M{"$in": status},
			"id":     taskId,
		}
	}
	total, errCount := m.db.Collection(ctx, model.Task{}.TableName()).CountDocuments(ctx, filter)
	if errCount != nil {
		log.ErrorfWithContext(ctx, "count status task error:%s", errCount.Error())
		return nil, page.PageResult{}, codes.ErrDatabase.Wrap(errCount)
	}
	skip := (pageParam.PageIndex - 1) * pageParam.PageSize
	dbRes, err := m.db.Collection(ctx, model.Task{}.TableName()).Find(ctx, filter, &options.FindOptions{Skip: &skip, Limit: &pageParam.PageSize, Sort: bson.M{"created_time": -1}})

	if err != nil {
		log.ErrorfWithContext(ctx, "get all status tasks from db error:%s", err.Error())
		return nil, page.PageResult{}, codes.ErrDatabase.Wrap(err)
	}
	tasks := make([]model.Task, 0)
	if errBind := dbRes.All(ctx, &tasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind all status tasks from db error:%s", errBind.Error())
		return nil, page.PageResult{}, codes.ErrDatabase.Wrap(errBind)
	}
	return tasks, page.NewPageResult(pageParam.PageSize, pageParam.PageIndex, total), nil
}

//GetStatusTaskForPagebyTaskIdFromDB 从数据库获得指定状态的任务，并分页
func (m *TaskManager) GetStatusTaskForPagebyMainTaskCodeFromDB(ctx context.Context, status []model.TaskStatus, pageParam page.Params, mainTaskCode string) ([]model.Task, page.PageResult, codes.Code) {
	page.SetPageParams(&pageParam.PageSize, &pageParam.PageIndex, 20)
	filter := bson.M{
		"main_task_code": bson.M{"$regex": mainTaskCode, "$options": "i"},
	}
	if len(status) > 0 {
		filter = bson.M{
			"status":         bson.M{"$in": status},
			"main_task_code": bson.M{"$regex": mainTaskCode, "$options": "i"},
		}
	}
	total, errCount := m.db.Collection(ctx, model.Task{}.TableName()).CountDocuments(ctx, filter)
	if errCount != nil {
		log.ErrorfWithContext(ctx, "count status task error:%s", errCount.Error())
		return nil, page.PageResult{}, codes.ErrDatabase.Wrap(errCount)
	}
	skip := (pageParam.PageIndex - 1) * pageParam.PageSize
	dbRes, err := m.db.Collection(ctx, model.Task{}.TableName()).Find(ctx, filter, &options.FindOptions{Skip: &skip, Limit: &pageParam.PageSize, Sort: bson.M{"created_time": -1}})
	if err != nil {
		log.ErrorfWithContext(ctx, "get all status tasks from db error:%s", err.Error())
		return nil, page.PageResult{}, codes.ErrDatabase.Wrap(err)
	}
	tasks := make([]model.Task, 0)
	if errBind := dbRes.All(ctx, &tasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind all status tasks from db error:%s", errBind.Error())
		return nil, page.PageResult{}, codes.ErrDatabase.Wrap(errBind)
	}
	return tasks, page.NewPageResult(pageParam.PageSize, pageParam.PageIndex, total), nil
}

//GetStatusTaskForPagebyKeysFromDB 从数据库获得指定状态的任务，并分页
func (m *TaskManager) GetStatusTaskForPagebyKeysFromDB(ctx context.Context, status []model.TaskStatus, pageParam page.Params, mainTaskCode string, taskId uint64) ([]model.Task, page.PageResult, codes.Code) {
	page.SetPageParams(&pageParam.PageSize, &pageParam.PageIndex, 20)
	filter := bson.M{}
	if taskId > 0 {
		filter["id"] = taskId
	}
	if mainTaskCode != "" {
		filter["main_task_code"] = bson.M{"$regex": mainTaskCode, "$options": "i"}
	}

	if len(status) > 0 {
		filter["status"] = bson.M{"$in": status}

		// filter = bson.M{
		// 	"status": bson.M{"$in": status},
		// }
	}
	total, errCount := m.db.Collection(ctx, model.Task{}.TableName()).CountDocuments(ctx, filter)
	if errCount != nil {
		log.ErrorfWithContext(ctx, "count status task error:%s", errCount.Error())
		return nil, page.PageResult{}, codes.ErrDatabase.Wrap(errCount)
	}
	skip := (pageParam.PageIndex - 1) * pageParam.PageSize
	dbRes, err := m.db.Collection(ctx, model.Task{}.TableName()).Find(ctx, filter, &options.FindOptions{Skip: &skip, Limit: &pageParam.PageSize, Sort: bson.M{"created_time": -1}})
	if err != nil {
		log.ErrorfWithContext(ctx, "get all status tasks from db error:%s", err.Error())
		return nil, page.PageResult{}, codes.ErrDatabase.Wrap(err)
	}
	tasks := make([]model.Task, 0)
	if errBind := dbRes.All(ctx, &tasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind all status tasks from db error:%s", errBind.Error())
		return nil, page.PageResult{}, codes.ErrDatabase.Wrap(errBind)
	}
	return tasks, page.NewPageResult(pageParam.PageSize, pageParam.PageIndex, total), nil
}

//GetRobotAssignTaskFromDB 从数据库查找机器人分配的任务
func (m *TaskManager) GetRobotAssignTaskFromDB(ctx context.Context, agvID string) (*model.Task, codes.Code) {
	dbRes := m.db.Collection(ctx, model.Task{}.TableName()).FindOne(ctx, bson.M{"agv_id": agvID, "status": bson.M{"$in": model.TaskAssignStatus()}})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get robot:%s assign task from db error:%s", agvID, dbRes.Err().Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find robot running:%s task",agvID)
		return nil, codes.ErrTaskNotExists
	}
	task := new(model.Task)
	if errBind := dbRes.Decode(task); errBind != nil {
		log.ErrorfWithContext(ctx, "bind robot assign task from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return task, nil
}
func (m *TaskManager) GetRobotIdleAvoidTaskFromDB(ctx context.Context, agvID string) (*model.Task, codes.Code) {
	dbRes := m.db.Collection(ctx, model.Task{}.TableName()).FindOne(ctx, bson.M{"agv_id": agvID, "type": model.TaskTypeAvoid, "status": bson.M{"$in": model.TaskAssignStatus()}})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get robot:%s assign task from db error:%s", agvID, dbRes.Err().Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find robot running:%s task",agvID)
		return nil, codes.ErrTaskNotExists
	}
	task := new(model.Task)
	if errBind := dbRes.Decode(task); errBind != nil {
		log.ErrorfWithContext(ctx, "bind robot assign task from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return task, nil
}
func (m *TaskManager) IsRobotTriggerIdleAvoidTask(ctx context.Context, agvID string) bool {
	dbRes := m.db.Collection(ctx, model.Task{}.TableName()).FindOne(ctx, bson.M{"avoid_agv": agvID, "type": model.TaskTypeAvoid, "status": bson.M{"$in": model.TaskAssignStatus()}})
	if dbRes.Err() != nil {
		return false
	}
	task := new(model.Task)
	if errBind := dbRes.Decode(task); errBind != nil {
		return false
	}
	if task.Status == model.TaskStatusAssign || task.Status == model.TaskStatusRegister {
		return false
	}
	return true
}

//GetRobotStatusTaskFromDB 从数据库查找机器人指定状态的任务
func (m *TaskManager) GetRobotStatusTaskFromDB(ctx context.Context, agvID string, status []model.TaskStatus) (*model.Task, codes.Code) {
	dbRes := m.db.Collection(ctx, model.Task{}.TableName()).FindOne(ctx, bson.M{"agv_id": agvID, "status": bson.M{"$in": status}})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get robot:%s running task from db error:%s", agvID, dbRes.Err().Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find robot running:%s task",agvID)
		return nil, codes.ErrTaskNotExists
	}
	task := new(model.Task)
	if errBind := dbRes.Decode(task); errBind != nil {
		log.ErrorfWithContext(ctx, "bind robot running task from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return task, nil
}

// 从数据库查找机器人运行中的任务(可用于自动重发的任务)
func (m *TaskManager) GetRobotRunningTaskForAutoRetryFromDB(ctx context.Context, agvID string) (*model.Task, codes.Code) {
	return m.GetRobotStatusTaskFromDB(ctx, agvID, model.TaskRunningTaskForAutoRetryStatus())
}

//GetRobotRunningTaskFromDB 从数据库查找机器人运行中的任务
func (m *TaskManager) GetRobotRunningTaskFromDB(ctx context.Context, agvID string) (*model.Task, codes.Code) {
	return m.GetRobotStatusTaskFromDB(ctx, agvID, model.TaskRunningStatus())
}

//GetRobotRunningTaskFromDB 从数据库查找机器人运行中的任务
func (m *TaskManager) GetRobotRunTaskFromDB(ctx context.Context, agvID string) (*model.Task, codes.Code) {
	return m.GetRobotStatusTaskFromDB(ctx, agvID, model.TaskRunStatus())
}

//GetTasksByMainTaskCodeFromDB 根据主任务编号从数据库查询任务
func (m *TaskManager) GetTasksByMainTaskCodeFromDB(ctx context.Context, mainTaskCode string) ([]model.Task, codes.Code) {
	dbRes, err := m.db.Collection(ctx, model.Task{}.TableName()).Find(ctx, bson.M{"main_task_code": mainTaskCode})
	if err != nil {
		log.ErrorfWithContext(ctx, "get main task code tasks from db error:%s", err.Error())
		return nil, codes.ErrDatabase.Wrap(err)
	}
	tasks := make([]model.Task, 0)
	if errBind := dbRes.All(ctx, &tasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind main task code tasks from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return tasks, nil
}

// 向数据库更新状态（只有已登记和已解析的任务或者状态改为完成和取消才可使用(需要删除所有子任务);有子任务的不可用此方法更新，需要使用UpdateSubtaskStatusToDB进行更新）
func (m *TaskManager) UpdateTaskStatusToDB(ctx context.Context, id uint64, taskStatus model.TaskStatus) codes.Code {
	log.Infof("update task:%d status:%s", id, m.taskStatusEnum[int(taskStatus)])
	data := bson.M{"status": taskStatus}
	if taskStatus == model.TaskStatusFinish {
		data["finish_time"] = time.Now()
	}
	// const maxRetries = 3
	// var retryCount int
	// var dbRes *mongo.SingleResult

	// for retryCount < maxRetries {
	// 	dbRes = m.db.Collection(ctx, model.Task{}.TableName()).FindOneAndUpdate(ctx, bson.M{"id": id}, bson.M{"$set": data})
	// 	if dbRes.Err() == nil {
	// 		break
	// 	}
	// 	if strings.Contains(dbRes.Err().Error(), "WriteConflict") {
	// 		// 设置随机数种子以确保每次运行都获得不同的随机数
	// 		rand.Seed(time.Now().UnixNano())
	// 		// 生成一个50到150之间的随机数
	// 		randomDelay := time.Duration(50+rand.Intn(100)) * time.Millisecond
	// 		// 使用该随机数进行延迟
	// 		time.Sleep(randomDelay)
	// 		retryCount++
	// 		// time.Sleep(100 * time.Millisecond) // 可以根据需要调整延迟时间
	// 		// retryCount++
	// 	} else {
	// 		// 如果错误不是写冲突，直接跳出循环
	// 		break
	// 	}
	// }

	dbRes := m.db.Collection(ctx, model.Task{}.TableName()).FindOneAndUpdate(ctx, bson.M{"id": id}, bson.M{"$set": data})

	if dbRes != nil && dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "update task:%d to db error:%s", id, dbRes.Err().Error())
		return codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find task:%d",id)
		return codes.ErrTaskNotExists
	}
	t := new(model.Task)
	if errBind := dbRes.Decode(t); errBind != nil {
		log.ErrorfWithContext(ctx, "bind task:%d from db error:%s", id, errBind.Error())
		return codes.ErrDatabase.Wrap(errBind)
	}
	if t.Status == model.TaskStatusCanceled && taskStatus != model.TaskStatusCanceled {
		log.Infof("task:%d任务状态 已取消，中断更新", id)
		return codes.ErrTaskNotExists
	}
	if t.Status == model.TaskStatusFinish && taskStatus != model.TaskStatusFinish {
		log.Infof("task:%d任务状态 已完成，中断更新", id)
		return codes.ErrTaskNotExists
	}

	commit := func() {
		t.Status = taskStatus
		finishedAt, find := data["finish_time"]
		if find {
			t.FinishTime = finishedAt.(time.Time)
		}
		m.sendTaskUpdate(t)
	}
	rollback := func() {}
	boot.TryAddTx(ctx, commit, rollback)
	return nil
}

func (m *TaskManager) UpdateFocuseTaskStatusToDB(ctx context.Context, id uint64, taskStatus model.TaskStatus, completeType model.CompleteType) codes.Code {
	log.Infof("update task:%d status:%s", id, m.taskStatusEnum[int(taskStatus)])
	data := bson.M{"status": taskStatus}
	if taskStatus == model.TaskStatusFinish {
		data["finish_time"] = time.Now()
	}
	data["complete_type"] = completeType
	dbRes := m.db.Collection(ctx, model.Task{}.TableName()).FindOneAndUpdate(ctx, bson.M{"id": id}, bson.M{"$set": data})

	if dbRes != nil && dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "update task:%d to db error:%s", id, dbRes.Err().Error())
		return codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find task:%d",id)
		return codes.ErrTaskNotExists
	}
	t := new(model.Task)
	if errBind := dbRes.Decode(t); errBind != nil {
		log.ErrorfWithContext(ctx, "bind task:%d from db error:%s", id, errBind.Error())
		return codes.ErrDatabase.Wrap(errBind)
	}
	if t.Status == model.TaskStatusCanceled && taskStatus != model.TaskStatusCanceled {
		log.Infof("task:%d任务状态 已取消，中断更新", id)
		return codes.ErrTaskNotExists
	}
	if t.Status == model.TaskStatusFinish && taskStatus != model.TaskStatusFinish {
		log.Infof("task:%d任务状态 已完成，中断更新", id)
		return codes.ErrTaskNotExists
	}

	commit := func() {
		t.Status = taskStatus
		finishedAt, find := data["finish_time"]
		if find {
			t.FinishTime = finishedAt.(time.Time)
		}
		m.sendTaskUpdate(t)
	}
	rollback := func() {}
	boot.TryAddTx(ctx, commit, rollback)
	return nil
}

// func (m *TaskManager) UpdateTaskStatusToDB123(ctx context.Context, id uint64, taskStatus model.TaskStatus) codes.Code {
// 	log.Infof("update task:%d status:%s", id, m.taskStatusEnum[int(taskStatus)])
// 	data := bson.M{"status": taskStatus}
// 	if taskStatus == model.TaskStatusFinish {
// 		data["finish_time"] = time.Now()
// 	}

// 	dbRes := m.db.Collection(ctx, model.Task{}.TableName()).FindOneAndUpdate(ctx, bson.M{"id": id}, bson.M{"$set": data})
// 	if dbRes != nil && dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
// 		log.ErrorfWithContext(ctx, "update task:%d to db error:%s", id, dbRes.Err().Error())
// 		return codes.ErrDatabase.Wrap(dbRes.Err())
// 	}
// 	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
// 		//log.Errorf("can not find task:%d",id)
// 		return codes.ErrTaskNotExists
// 	}
// 	t := new(model.Task)
// 	if errBind := dbRes.Decode(t); errBind != nil {
// 		log.ErrorfWithContext(ctx, "bind task:%d from db error:%s", id, errBind.Error())
// 		return codes.ErrDatabase.Wrap(errBind)
// 	}
// 	if t.Status == model.TaskStatusCanceled && taskStatus != model.TaskStatusCanceled {
// 		log.Infof("task:%d任务状态 已取消，中断更新", id)
// 		return codes.ErrTaskNotExists
// 	}
// 	if t.Status == model.TaskStatusFinish && taskStatus != model.TaskStatusFinish {
// 		log.Infof("task:%d任务状态 已完成，中断更新", id)
// 		return codes.ErrTaskNotExists
// 	}

// 	commit := func() {
// 		t.Status = taskStatus
// 		finishedAt, find := data["finish_time"]
// 		if find {
// 			t.FinishTime = finishedAt.(time.Time)
// 		}
// 		m.sendTaskUpdate(t)
// 	}
// 	rollback := func() {}
// 	boot.TryAddTx(ctx, commit, rollback)
// 	return nil
// }

//UpdateStatusToDB 向数据库更新状态（要更新的状态只可为已分配、已解析）和agvId
func (m *TaskManager) UpdateStatusAgvIdToDB(ctx context.Context, id uint64, taskStatus model.TaskStatus, agvId string) codes.Code {
	log.Infof("update task:%d status:%s robot:%s", id, m.taskStatusEnum[int(taskStatus)], agvId)
	// if taskStatus != model.TaskStasusResolved || taskStatus != model.TaskStatusAssign {
	// 	log.Errorf("向数据库更新状态错误，状态只可为已分配、已解析 task:%d status to:%d", id, taskStatus)
	// 	return codes.ErrTaskStart
	// }
	data := bson.M{"status": taskStatus, "agv_id": agvId}
	if taskStatus == model.TaskStasusResolved {
		data["start_time"] = time.Now()
	}
	dbRes := m.db.Collection(ctx, model.Task{}.TableName()).FindOneAndUpdate(ctx, bson.M{"id": id}, bson.M{"$set": data})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "update task:%d to db error:%s", id, dbRes.Err().Error())
		return codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find task:%d",id)
		return codes.ErrTaskNotExists
	}
	t := new(model.Task)
	if errBind := dbRes.Decode(t); errBind != nil {
		log.ErrorfWithContext(ctx, "bind task:%d from db error:%s", id, errBind.Error())
		return codes.ErrDatabase.Wrap(errBind)
	}
	if t.Status == model.TaskStatusCanceled || t.Status == model.TaskStatusFinish {
		log.Infof("task:%d任务状态 已取消或已完成，中断更新", id)
		return codes.ErrTaskNotExists
	}
	commit := func() {
		t.Status = taskStatus
		finishedAt, find := data["finish_time"]
		if find {
			t.FinishTime = finishedAt.(time.Time)
		}
		m.sendTaskUpdate(t)
	}
	rollback := func() {}
	boot.TryAddTx(ctx, commit, rollback)
	return nil
}
func (m *TaskManager) UpdateTaskAgvIdToDB(ctx context.Context, mainTaskCode string, agvId string) codes.Code {
	dbRes := m.db.Collection(ctx, model.Task{}.TableName()).FindOneAndUpdate(ctx, bson.M{"main_task_code": mainTaskCode, "type": model.TaskTypePut}, bson.M{"$set": bson.M{"agv_id": agvId}})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		return codes.ErrDatabase.Wrap(dbRes.Err())
	}
	return nil
}
func (m *TaskManager) UpdateTaskTargetToDB(ctx context.Context, taskId uint64, targetId string) codes.Code {
	dbRes := m.db.Collection(ctx, model.Task{}.TableName()).FindOneAndUpdate(ctx, bson.M{"id": taskId}, bson.M{"$set": bson.M{"target_site_id": targetId}})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		return codes.ErrDatabase.Wrap(dbRes.Err())
	}
	return nil
}
func (m *TaskManager) UpdateSubtaskTargetToDB(ctx context.Context, taskId uint64, oldtargetId, targetId string) codes.Code {
	dbRes := m.db.Collection(ctx, model.Subtask{}.TableName()).FindOneAndUpdate(ctx, bson.M{"task_id": taskId, "target_site_id": oldtargetId, "type": model.TaskTypePut}, bson.M{"$set": bson.M{"target_site_id": targetId}})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		return codes.ErrDatabase.Wrap(dbRes.Err())
	}
	return nil
}

//删除未执行的待命任务
func (m *TaskManager) DeleteRobotStandByTaskToDB(ctx context.Context, agvID string) codes.Code {
	// m.UpdateLock.Lock()
	// defer m.UpdateLock.Unlock()
	dbRes := m.db.Collection(ctx, model.Task{}.TableName()).FindOne(ctx, bson.M{"agv_id": agvID, "type": model.TaskTypeStandBy, "status": bson.M{"$in": []model.TaskStatus{model.TaskStatusRegister, model.TaskStatusAssign}}})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "delete robot:%s type:%s status :%d task:%s to db error:%s", agvID, model.TaskTypeStandBy, model.TaskWaitingStatus(), dbRes.Err().Error())
		return codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		return nil
	}
	task := new(model.Task)
	if errBind := dbRes.Decode(task); errBind != nil {
		log.ErrorfWithContext(ctx, "bind robot running task from db error:%s", errBind.Error())
		return codes.ErrDatabase.Wrap(errBind)
	}

	//更新
	id := task.Id
	taskStatus := model.TaskStatusCanceled
	log.Infof("update stand by task:%d status:%s", task.Id, m.taskStatusEnum[int(taskStatus)])
	data := bson.M{"status": taskStatus}
	if taskStatus == model.TaskStatusFinish {
		data["finish_time"] = time.Now()
	}

	dbRes1 := m.db.Collection(ctx, model.Task{}.TableName()).FindOneAndUpdate(ctx, bson.M{"id": id}, bson.M{"$set": data})
	// dbRes := m.db.Collection(ctx, model.Task{}.TableName()).FindOneAndUpdate(ctx, bson.M{"id": id}, bson.M{"$set": data})

	if dbRes1 != nil && dbRes1.Err() != nil && !errors.Is(dbRes1.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "update task:%d canceled to db error:%s", id, dbRes1.Err().Error())
		return codes.ErrDatabase.Wrap(dbRes1.Err())
	}
	if dbRes1.Err() != nil && errors.Is(dbRes1.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find task:%d",id)
		return nil
	}
	return nil

	// return m.UpdateTaskStatusToDB(ctx, task.Id, model.TaskStatusCanceled)
}

//IsRobotAssignTypeTask 机器人是否已分配指定类型的任务
func (m *TaskManager) IsRobotAssignTypeTask(ctx context.Context, agvID string, taskType model.TaskType) (bool, codes.Code) {
	count, err := m.db.Collection(ctx, model.Task{}.TableName()).CountDocuments(ctx, bson.M{"agv_id": agvID, "type": taskType, "status": bson.M{"$in": model.TaskAssignStatus()}})
	if err != nil {
		log.ErrorfWithContext(ctx, "count robot type tasks from db error:%s", err.Error())
		return false, codes.ErrDatabase.Wrap(err)
	}
	return count > 0, nil
}

//IsRobotAssignMainTask 机器人是否已分配主任务
func (m *TaskManager) IsRobotAssignMainTask(ctx context.Context, agvID string) (bool, codes.Code) {
	count, err := m.db.Collection(ctx, model.MainTask{}.TableName()).CountDocuments(ctx, bson.M{"agv_id": agvID})
	if err != nil {
		log.ErrorfWithContext(ctx, "count robot main task from db error:%s", err.Error())
		return false, codes.ErrDatabase.Wrap(err)
	}
	return count > 0, nil
}

//更新任务绑定记录到数据库
func (m *TaskManager) AddMainTaskToDB(ctx context.Context, mainTaskCode string, taskId uint64, agvId string) codes.Code {
	m.bindMainTaskLocker.Lock()
	defer m.bindMainTaskLocker.Unlock()
	dbRes := m.db.Collection(ctx, model.MainTask{}.TableName()).FindOneAndReplace(ctx, bson.M{"agv_id": agvId}, model.MainTask{MainTaskCode: mainTaskCode, TaskId: taskId, AgvId: agvId}, &options.FindOneAndReplaceOptions{Upsert: function.BoolPtr(true)})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "add main task to db error:%s", dbRes.Err().Error())
		return codes.ErrDatabase.Wrap(dbRes.Err())
	}
	return nil
}

//先查后赋值
func (m *TaskManager) UpdateMainTaskIdToDB(ctx context.Context, mainTaskCode string, taskId uint64, agvId string) codes.Code {
	m.bindMainTaskLocker.Lock()
	defer m.bindMainTaskLocker.Unlock()
	//先查询
	dbRes := m.db.Collection(ctx, model.MainTask{}.TableName()).FindOne(ctx, bson.M{"main_task_code": mainTaskCode})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get robot main task from db error:%s", dbRes.Err().Error())
		return codes.ErrDatabase.Wrap(dbRes.Err())
	}

	//为空，直接成功
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find robot:%s main task",agvID)
		return nil
	}
	bindTask := new(model.MainTask)
	if errBind := dbRes.Decode(bindTask); errBind != nil {
		log.ErrorfWithContext(ctx, "bind main task error:%s", errBind.Error())
		return codes.ErrTaskNotExists.Wrap(errBind)
	}

	//根据绑定的mainTask,判断当前绑定的任务编号
	//为0，直接成功
	log.Warnf("robot:%s 获得数据库绑定任务编号:%d,当前任务的id:%d", agvId, bindTask.TaskId, taskId)
	if bindTask.TaskId == taskId {
		return nil
	}
	//有新的绑定，直接成功
	if bindTask.TaskId != taskId && taskId != 0 && bindTask.TaskId != 0 {
		return nil
	}
	//清除0操作
	dbRes123 := m.db.Collection(ctx, model.MainTask{}.TableName()).FindOneAndReplace(ctx, bson.M{"agv_id": agvId}, model.MainTask{MainTaskCode: mainTaskCode, TaskId: taskId, AgvId: agvId}, &options.FindOneAndReplaceOptions{Upsert: function.BoolPtr(true)})
	if dbRes123.Err() != nil && !errors.Is(dbRes123.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "add main task to db error:%s", dbRes123.Err().Error())
		return codes.ErrDatabase.Wrap(dbRes123.Err())
	}
	return nil
}

//先查后赋值
func (m *TaskManager) UpdateMainTaskToDB(ctx context.Context, mainTaskCode string, taskId uint64, agvId string) codes.Code {
	m.bindMainTaskLocker.Lock()
	defer m.bindMainTaskLocker.Unlock()
	//先查询
	dbRes := m.db.Collection(ctx, model.MainTask{}.TableName()).FindOne(ctx, bson.M{"main_task_code": mainTaskCode})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get robot main task from db error:%s", dbRes.Err().Error())
		return codes.ErrDatabase.Wrap(dbRes.Err())
	}

	//为空，直接成功
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find robot:%s main task",agvID)
		return nil
	}
	bindTask := new(model.MainTask)
	if errBind := dbRes.Decode(bindTask); errBind != nil {
		log.ErrorfWithContext(ctx, "bind main task error:%s", errBind.Error())
		return codes.ErrTaskNotExists.Wrap(errBind)
	}

	//根据绑定的mainTask,判断当前绑定的任务编号
	//为0，直接成功
	log.Warnf("robot:%s 获得数据库绑定任务编号:%d,当前任务的id:%d", agvId, bindTask.TaskId, taskId)
	if bindTask.TaskId == 0 {
		return nil
	}
	//有新的绑定，直接成功
	if bindTask.TaskId != taskId {
		return nil
	}

	//清除0操作
	dbRes123 := m.db.Collection(ctx, model.MainTask{}.TableName()).FindOneAndReplace(ctx, bson.M{"agv_id": agvId}, model.MainTask{MainTaskCode: mainTaskCode, TaskId: 0, AgvId: agvId}, &options.FindOneAndReplaceOptions{Upsert: function.BoolPtr(true)})
	if dbRes123.Err() != nil && !errors.Is(dbRes123.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "add main task to db error:%s", dbRes123.Err().Error())
		return codes.ErrDatabase.Wrap(dbRes123.Err())
	}
	return nil
}

//DeleteMainTaskToDB 删除机器人主任务绑定
func (m *TaskManager) DeleteMainTaskToDB(ctx context.Context, mainTaskCode string) codes.Code {
	_, err := m.db.Collection(ctx, model.MainTask{}.TableName()).DeleteOne(ctx, bson.M{"main_task_code": mainTaskCode})
	if err != nil && !errors.Is(err, mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "delete main task:%s to db error:%s", mainTaskCode, err.Error())
		return codes.ErrDatabase.Wrap(err)
	}
	return nil
}

//DeleteMainTaskToDB 删除机器人主任务绑定
func (m *TaskManager) DeleteMainTaskByAgvIdToDB(ctx context.Context, agvId string) codes.Code {
	_, err := m.db.Collection(ctx, model.MainTask{}.TableName()).DeleteOne(ctx, bson.M{"agv_id": agvId})
	if err != nil && !errors.Is(err, mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "delete main robot:%s to db error:%s", agvId, err.Error())
		return codes.ErrDatabase.Wrap(err)
	}
	return nil
}

//获取主任务号下的第一条任务
func (m *TaskManager) GetFirstTaskByMainTaskCodeFromDB(ctx context.Context, mainTaskCode string) (*model.Task, codes.Code) {
	dbRes := m.db.Collection(ctx, model.Task{}.TableName()).FindOne(ctx, bson.M{"main_task_code": mainTaskCode}, &options.FindOneOptions{Sort: bson.M{"created_time": 1}})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get main task from db error:%s", dbRes.Err().Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find main task:%s",mainTaskCode)
		return nil, codes.ErrTaskNotExists
	}
	task := new(model.Task)
	if errBind := dbRes.Decode(task); errBind != nil {
		log.ErrorfWithContext(ctx, "bind main task error:%s", errBind.Error())
		return nil, codes.ErrTaskNotExists.Wrap(errBind)
	}
	return task, nil
}

//获取主任务号下的第一条未完成任务
func (m *TaskManager) GetFirstWaitingTaskByMainTaskCodeFromDB(ctx context.Context, mainTaskCode string) (*model.Task, codes.Code) {
	tasks, err := m.GetAllTasksByMainTaskCodeFromDB(ctx, mainTaskCode)
	if err != nil {
		return nil, err
	}
	for _, task := range tasks {
		if task.Status.IsDone() {
			continue
		}
		return task, nil
	}
	return nil, codes.ErrTaskNotExists
}

//获取主任务号下所有任务
func (m *TaskManager) GetAllTasksByMainTaskCodeFromDB(ctx context.Context, mainTaskCode string) ([]*model.Task, codes.Code) {
	dbRes, err := m.db.Collection(ctx, model.Task{}.TableName()).Find(ctx, bson.M{"main_task_code": mainTaskCode}, &options.FindOptions{Sort: bson.M{"created_time": 1}})
	if err != nil {
		log.ErrorfWithContext(ctx, "get main task from db error:%s", dbRes.Err().Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	tasks := make([]*model.Task, 0)
	if errBind := dbRes.All(ctx, &tasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind main tasks error:%s", errBind.Error())
		return nil, codes.ErrTaskNotExists.Wrap(errBind)
	}
	return tasks, nil
}

//GetMainTaskFromDB 获得主任务
func (m *TaskManager) GetMainTaskFromDB(ctx context.Context, mainTaskCode string) (*model.MainTask, codes.Code) {
	dbRes := m.db.Collection(ctx, model.MainTask{}.TableName()).FindOne(ctx, bson.M{"main_task_code": mainTaskCode})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get main task from db error:%s", dbRes.Err().Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find main task:%s",mainTaskCode)
		return nil, codes.ErrTaskNotExists
	}
	task := new(model.MainTask)
	if errBind := dbRes.Decode(task); errBind != nil {
		log.ErrorfWithContext(ctx, "bind main task error:%s", errBind.Error())
		return nil, codes.ErrTaskNotExists.Wrap(errBind)
	}
	return task, nil
}

//根据小车ID获取任务绑定信息
func (m *TaskManager) GetMainTaskByAgvFromDB(ctx context.Context, agvId string) (*model.MainTask, codes.Code) {
	dbRes := m.db.Collection(ctx, model.MainTask{}.TableName()).FindOne(ctx, bson.M{"agv_id": agvId})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get main task from db error:%s", dbRes.Err().Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find main task:%s",mainTaskCode)
		return nil, nil
	}
	task := new(model.MainTask)
	if errBind := dbRes.Decode(task); errBind != nil {
		log.ErrorfWithContext(ctx, "bind main task error:%s", errBind.Error())
		return nil, codes.ErrTaskNotExists.Wrap(errBind)
	}
	return task, nil
}

//GetAllMainTasksFromDB 获得所有主任务流绑定信息
func (m *TaskManager) GetAllMainTasksFromDB(ctx context.Context) ([]*model.MainTask, codes.Code) {
	dbRes, err := m.db.Collection(ctx, model.MainTask{}.TableName()).Find(ctx, bson.M{})
	if err != nil {
		log.ErrorfWithContext(ctx, "get main task from db error:%s", err)
		return nil, codes.ErrDatabase.Wrap(err)
	}
	tasks := make([]*model.MainTask, 0)
	if errBind := dbRes.All(ctx, &tasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind main tasks error:%s", errBind.Error())
		return nil, codes.ErrTaskNotExists.Wrap(errBind)
	}
	return tasks, nil
}

//GetRobotMainTaskFromDB 获得机器人主任务
func (m *TaskManager) GetRobotMainTaskFromDB(ctx context.Context, agvID string) (*model.MainTask, codes.Code) {
	dbRes := m.db.Collection(ctx, model.MainTask{}.TableName()).FindOne(ctx, bson.M{"agv_id": agvID})
	if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		log.ErrorfWithContext(ctx, "get robot main task from db error:%s", dbRes.Err().Error())
		return nil, codes.ErrDatabase.Wrap(dbRes.Err())
	}
	if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
		//log.Errorf("can not find robot:%s main task",agvID)
		return nil, codes.ErrTaskNotExists
	}
	task := new(model.MainTask)
	if errBind := dbRes.Decode(task); errBind != nil {
		log.ErrorfWithContext(ctx, "bind main task error:%s", errBind.Error())
		return nil, codes.ErrTaskNotExists.Wrap(errBind)
	}
	return task, nil
}

//AddEfficency 添加稼动率统计
func (m *TaskManager) AddEfficency(ctx context.Context, agvID string, startAt, finishAt time.Time) codes.Code {
	date := time.Now().Local().Format("2006-01-02")
	count, err := m.db.Collection(ctx, model.Efficency{}.TableName()).CountDocuments(ctx, bson.M{"agv_id": agvID, "start_time": date})
	if err != nil {
		log.ErrorfWithContext(ctx, "get task effiency to db error:%s", err.Error())
		return codes.ErrDatabase.Wrap(err)
	}
	totalTime := finishAt.Sub(startAt).Hours()
	//任务执行时间超过1小时不计算
	if totalTime > 1 {
		return nil
	}
	if count == 0 {
		now := time.Now().Local()
		dateTime := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local)
		_, dbRes := m.db.Collection(ctx, model.Efficency{}.TableName()).InsertOne(ctx, &model.Efficency{AGVId: agvID, StartTime: date, Time: dateTime, TotalTime: totalTime})
		if dbRes != nil {
			log.ErrorfWithContext(ctx, "insert task effiency to db error:%s", dbRes.Error())
			return codes.ErrDatabase.Wrap(dbRes)
		}
		return nil
	}
	dbRes := m.db.Collection(ctx, model.Efficency{}.TableName()).FindOneAndUpdate(ctx, bson.M{"agv_id": agvID, "start_time": date}, bson.M{"$inc": bson.M{"total_time": finishAt.Sub(startAt).Hours(), "task_num": 1}})
	if dbRes.Err() != nil {
		log.ErrorfWithContext(ctx, "get task effiency to db error:%s", dbRes.Err().Error())
		return codes.ErrDatabase.Wrap(dbRes.Err())
	}
	return nil
}

//GetEfficencyFromDB 从数据库获得稼动率数据统计
func (m *TaskManager) GetEfficencyFromDB(ctx context.Context, agvID string, from, end time.Time) ([]model.Efficency, codes.Code) {
	if end.IsZero() {
		end = time.Now()
	}
	filter := bson.M{"time": bson.M{"$gte": from, "$lte": end}}
	if agvID != "" {
		filter["agv_id"] = agvID
	}
	dbRes, err := m.db.Collection(ctx, model.Efficency{}.TableName()).Find(ctx, filter)
	if err != nil {
		log.ErrorfWithContext(ctx, "get task effiency from db error:%s", err.Error())
		return nil, codes.ErrDatabase.Wrap(err)
	}
	efficency := make([]model.Efficency, 0)
	if errBind := dbRes.All(ctx, &efficency); errBind != nil {
		log.ErrorfWithContext(ctx, "bind task effiency from db error:%s", errBind.Error())
		return nil, codes.ErrDatabase.Wrap(errBind)
	}
	return efficency, nil
}

//StartAutoCleanDB 数据库自动清理
func (m *TaskManager) StartAutoCleanDB(days int) {
	go func() {
		for {
			ctx := context.TODO()
			_, err := m.db.Collection(ctx, model.Task{}.TableName()).DeleteMany(ctx, bson.M{"created_time": bson.M{"$lte": time.Now().Add(-time.Duration(days) * 24 * time.Hour)}})
			if err != nil && !errors.Is(err, mongo.ErrNoDocuments) {
				log.ErrorfWithContext(ctx, "delete robot task from db error:%s", err.Error())
			}
			time.Sleep(1 * time.Hour)
		}
	}()
}

//GetStatusUpdateChan 获得任务状态推送channel
func (m *TaskManager) GetStatusUpdateChan() <-chan model.Task {
	return m.taskStatusUpdateChan
}

//sendTaskUpdate 推送任务状态更新
func (m *TaskManager) sendTaskUpdate(t *model.Task) {
	m.taskStatusUpdateChan <- *t
}

//========================
//func (m *TaskManager) IsRobotAssignStandbyTask(ctx context.Context, agvID string) (bool, codes.Code) {
//	count := int64(0)
//	if err := m.db.WithContext(ctx).Model(model.Task{}).Where("(status IN ?) AND agv_id = ? AND type = ?", []model.TaskStatus{model.TaskStatusRegister, model.TaskStatusWaitAssign, model.TaskStatusRunning, model.TaskStatusPaused}, agvID, model.TaskTypeStandBy).Count(&count).Error; err != nil {
//		log.ErrorfWithContext(ctx, "check robot standby task from db error:%s", err.Error())
//		return false, codes.ErrDatabase.Wrap(err)
//	}
//	return count > 0, nil
//}
//
//func (m *TaskManager) IsRobotAssignChargeTask(ctx context.Context, agvID string) (bool, codes.Code) {
//	count := int64(0)
//	if err := m.db.WithContext(ctx).Model(model.Task{}).Where("(status = ? OR status = ?) AND agv_id = ? AND type = ?", model.TaskStatusRunning, model.TaskStatusPaused, agvID, model.TaskTypeCharge).Count(&count).Error; err != nil {
//		log.ErrorfWithContext(ctx, "check robot charge task from db error:%s", err.Error())
//		return false, codes.ErrDatabase.Wrap(err)
//	}
//	return count > 0, nil
//}

//任务优先级更改(已启用事务)
func (m *TaskManager) TaskGradeChange(ctx context.Context, taskIds []uint64, grade uint) codes.Code {
	dbRes, err := m.db.Collection(ctx, model.Task{}.TableName()).Find(ctx, bson.M{"id": bson.M{"$in": taskIds}})
	if err != nil {
		log.ErrorfWithContext(ctx, "get all waiting tasks from db error:%s", err.Error())
		return codes.ErrDatabase.Wrap(err)
	}
	tasks := make([]*model.Task, 0)
	if errBind := dbRes.All(ctx, &tasks); errBind != nil {
		log.ErrorfWithContext(ctx, "bind all waiting tasks from db error:%s", errBind.Error())
		return codes.ErrDatabase.Wrap(errBind)
	}
	for _, task := range tasks {
		if task.Status != model.TaskStatusRegister {
			return codes.ErrTaskStatusNotMatch
		}
	}

	ctxTx := boot.Begin(ctx)
	for _, taskId := range taskIds {
		data := bson.M{"grade": grade}
		dbRes := m.db.Collection(ctxTx, model.Task{}.TableName()).FindOneAndUpdate(ctxTx, bson.M{"id": taskId}, bson.M{"$set": data})
		if dbRes.Err() != nil && !errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
			log.ErrorfWithContext(ctx, "update report task:%d to db error:%s", taskId, dbRes.Err().Error())
			ctxTx.Rollback()
			return codes.ErrDatabase.Wrap(dbRes.Err())
		}
		if dbRes.Err() != nil && errors.Is(dbRes.Err(), mongo.ErrNoDocuments) {
			ctxTx.Rollback()
			return codes.ErrTaskNotExists
		}
	}
	ctxTx.Commit()
	return nil
}
